import json
import random
import string
from datetime import time

import arrow
import captcha
import requests
from captcha.image import ImageCaptcha
from flask import Blueprint, request, redirect, make_response, Response, jsonify
from application.models.model import User, Role, role_user, BrokerUser
from cache import my_cache
from db_init import db
from swaager_init import siwa
from sqlalchemy.exc import IntegrityError
from flask_login import login_user, login_required, current_user

from tools.broker_api import get_token_by_code, get_warrant_url
from tools.data_tools import orm2dict, ret_route
from my_config import VIP_END_TIME, LOGIN_APP_MAP, LOGIN_APP_URL

user_blue = Blueprint("user", __name__)

from pydantic import BaseModel


class RegisterBody(BaseModel):
    nikename: str
    mobile: int
    password: str


@user_blue.route("/register", methods=['POST'])
def register():
    user_data = dict(RegisterBody(**request.json))
    uuid = request.args.get('uuid')
    imgcode = user_data.pop('imgcode')

    broker = user_data.pop('broker') if 'broker' in user_data else None
    broker_uid = user_data.pop('broker_id') if 'broker_id' in user_data else None

    # 校验
    code = my_cache.get(uuid)
    my_cache.delete(uuid)
    if not code or imgcode.lower() != code.decode():
        return ret_route(data={'name': 'sadf'})

    try:
        user = User(**user_data)
        db.session.add(user)
        db.session.flush()
        db.session.commit()
        if broker and broker_uid:
            bu = BrokerUser(broker_name=broker, broker_uid=broker_uid, uid=user.id)
            db.session.add(bu)
        return {"code": 200, 'msg': '注册成功', 'data': {'user_id': user.id}}
    except IntegrityError as e:
        print(e)
        return {"code": 206, 'msg': '账号已存在', 'data': {}}


@user_blue.route("/login", methods=['POST'])
def login():
    user_data = request.json
    user = User.query.filter_by(**user_data).first()

    broker = user_data.pop('broker') if 'broker' in user_data else None
    broker_uid = user_data.pop('broker_id') if 'broker_id' in user_data else None
    if broker and broker_uid:
        bu = BrokerUser(broker_name=broker, broker_uid=broker_uid, uid=user.id)
        db.session.add(bu)
        db.session.commit()

    if user:
        login_user(user)
        user_data = orm2dict(user)
        user_data['role_powers'] = {role.name: orm2dict(role.power) for role in user.role}
        return {"code": 200, 'msg': '登录成功', 'data': user_data}
    return {"code": 403, 'msg': '请输入正确的账号密码', 'data': {}}


@user_blue.route("/imgcode", methods=['GET'])
def get_imgcode():
    uuid = request.args.get('uuid')
    img_string = ''.join(random.sample(string.digits + string.ascii_letters, 4))
    img = ImageCaptcha()
    img_code = img.generate(img_string)

    # 写入redis
    my_cache.set(name=uuid, value=img_string.lower(), ex=300)
    return ret_route(data=Response(img_code, mimetype='image/png'))


@user_blue.route("/vip", methods=['post'])
@login_required
def buy_vip():
    role_id = request.json.get('role_id')
    end_t = arrow.now().int_timestamp + VIP_END_TIME
    current_user.vip = 1
    current_user.end_t = end_t
    current_user.role.append(Role.query.get(role_id))
    db.session.query(role_user).filter_by(role_id=role_id, user_id=current_user.id).update({'end_t': end_t})
    db.session.commit()
    return {'code': 200, 'msg': '角色已添加'}


@user_blue.route("/login/<any(weibo,github,gitee):broker>", methods=['GET'])
def broker_login(broker):
    return ret_route(3002, data=get_warrant_url(broker))


@user_blue.route("/weiboCallback/", methods=['get'])
def weibo_callback():
    code = request.args.get('code')
    token, uid = get_token_by_code('weibo', code)

    broker_user = BrokerUser.query.filter_by(broker_uid=uid, broker_name='weibo').first()

    if broker_user and broker_user.user:
        login_user(broker_user.user)
        return ret_route(2000)

    return ret_route(3002, data='weibo_api')


@user_blue.route("/login", methods=['get'])
def test_login():
    uid = request.args.get('uid')
    user = User.query.get(uid)
    login_user(user)
    return {"code": 200, 'msg': '登录成功'}
